﻿//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Common
//  File name:	RulesFactory.cs
//  Developer:	Solomatov Igor
//  Created:	15.04.2012
// 
//  -------------------- iSharePoint -------------------- //

using System;
using System.Collections.Generic;

namespace Smart.Common.Rules
{
	/// <summary>
	/// Rules factory
	/// </summary>
	public class RulesFactory : IRulesFactory
	{
		public SPServicesInstance Services { get; set; }

		public RulesFactory(SPServicesInstance services)
		{
			Services = services;
		}

		/// <summary>
		/// Register rules service
		/// </summary>
		/// <typeparam name="TRuleServiceType">Service type</typeparam>
		/// <param name="serviceName">Rules service name</param>
		public static void Register<TRuleServiceType>(string serviceName)
			where TRuleServiceType : class, IRulesService, new()
		{
			SPServices.ServiceLocator.Register<IRulesService, TRuleServiceType>(serviceName);
		}

		/// <summary>
		/// Unregister rules service
		/// </summary>
		/// <param name="serviceName">Rules service name</param>
		public static void Unregister(string serviceName)
		{
			SPServices.ServiceLocator.Unregister<IRulesService>(serviceName);
		}

		/// <summary>
		/// Create rules service
		/// </summary>
		/// <param name="serviceName">Rules service name</param>
		/// <returns>Rules service</returns>
		protected IRulesService Get(string serviceName)
		{
			return Services.ServiceLocator.GetInstance<IRulesService>(serviceName);
		}

		/// <summary>
		/// Get rules service
		/// </summary>
		/// <param name="serviceName">Rules service name</param>
		/// <returns>Service</returns>
		public virtual IRulesService GetService(string serviceName)
		{
			var service = Get(serviceName);

			if (service == null)
				throw new ArgumentOutOfRangeException("serviceName: " + serviceName);

			service.InitContext(serviceName);

			service.InitService();

			return service;
		}

		/// <summary>
		/// Create new securable filter
		/// </summary>
		public virtual RulesFilter CreateFilter(string serviceName)
		{
			var service = GetService(serviceName);

			return service.CreateFilter();
		}

		/// <summary>
		/// Load instance
		/// </summary>
		public virtual IRulesInstance LoadInstance(string serviceName, string instanceId)
		{
			var service = GetService(serviceName);

			return service.LoadInstance(instanceId);
		}

		/// <summary>
		/// Load instance
		/// </summary>
		public virtual IRulesInstance LoadInstance(string serviceName, RulesFilter filter)
		{
			var service = GetService(serviceName);

			return service.LoadInstance(filter);
		}

		/// <summary>
		/// Check rules for instance
		/// </summary>
		/// <returns>true, if some rules' actions applied</returns>
		public virtual bool Execute(string serviceName, string instanceId)
		{
			var service = GetService(serviceName);

			return service.Execute(instanceId);
		}

		/// <summary>
		/// Check rules for instance
		/// </summary>
		/// <returns>true, if some rules' actions applied</returns>
		public virtual bool Execute<TInstanceType>(string serviceName, TInstanceType instance)
			where TInstanceType : class, IRulesInstance
		{
			var service = GetService(serviceName);

			return service.Execute(instance);
		}

		/// <summary>
		/// Check rule's condition and execute action 
		/// </summary>
		/// <returns>true, if condition is fulfilled and action applied</returns>
		public virtual bool Execute<TRuleType, TInstanceType>(string serviceName, TRuleType rule, TInstanceType instance, IDictionary<string, object> variables)
			where TRuleType : class, IRule
			where TInstanceType : class, IRulesInstance
		{
			var service = GetService(serviceName);

			return service.Execute(rule, instance, variables);
		}

		/// <summary>
		/// Check rule's condition
		/// </summary>
		/// <returns>true, if condition is fulfilled and action applied</returns>
		public virtual bool Execute<TInstanceType>(string serviceName, object rule, TInstanceType instance, IDictionary<string, object> variables)
			where TInstanceType : class, IRulesInstance
		{
			var service = GetService(serviceName);

			return service.Execute(rule, instance, variables);
		}

		/// <summary>
		/// Check rule's condition for instance
		/// </summary>
		public virtual bool Check<TRuleCondition, TInstanceType>(string serviceName, TRuleCondition ruleCondition, TInstanceType instance, IDictionary<string, object> variables)
			where TRuleCondition : class, IRuleCondition
			where TInstanceType : class, IRulesInstance
		{
			var service = GetService(serviceName);

			return service.Check(ruleCondition, instance, variables);
		}

		/// <summary>
		/// Check rule's condition for instance
		/// </summary>
		public virtual bool Check<TInstanceType>(string serviceName, object ruleCondition, TInstanceType instance, IDictionary<string, object> variables)
			where TInstanceType : class, IRulesInstance
		{
			var service = GetService(serviceName);

			return service.Check(ruleCondition, instance, variables);
		}

		/// <summary>
		/// Execute rule's action for instance
		/// </summary>
		public virtual bool Apply<TRuleAction, TInstanceType>(string serviceName, TRuleAction ruleAction, TInstanceType instance, IDictionary<string, object> variables)
			where TRuleAction : class, IRuleAction
			where TInstanceType : class, IRulesInstance
		{
			var service = GetService(serviceName);

			return service.Apply(ruleAction, instance, variables);
		}

		/// <summary>
		/// Execute rule's action for instance
		/// </summary>
		public virtual bool Apply<TInstanceType>(string serviceName, object ruleAction, TInstanceType instance, IDictionary<string, object> variables)
			where TInstanceType : class, IRulesInstance
		{
			var service = GetService(serviceName);

			return service.Apply(ruleAction, instance, variables);
		}
	}
}